package cn.getech.data.development.utils;


import com.alibaba.nacos.client.utils.StringUtils;
import com.jcraft.jsch.*;
import org.apache.commons.io.IOUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.*;
import java.net.URL;
import java.util.*;

/**
 * @author lxx
 * @date 2021/8/12
 */
public class SFTPUtil {
    private transient Logger log = LoggerFactory.getLogger(this.getClass());

    private ChannelSftp sftp;

    private Session session;
    /**
     * SFTP 登录用户名
     */
    private String username;
    /**
     * SFTP 登录密码
     */
    private String password;
    /**
     * 私钥
     */
    private String privateKey;
    /**
     * SFTP 服务器地址IP地址
     */
    private String host;
    /**
     * SFTP 端口
     */
    private int port;


    /**
     * 构造基于密码认证的sftp对象
     */
    public SFTPUtil(String username, String password, String host, int port) {
        this.username = username;
        this.password = password;
        this.host = host;
        this.port = port;
    }

    /**
     * 构造基于秘钥认证的sftp对象
     */
    public SFTPUtil(String username, String host, int port, String privateKey) {
        this.username = username;
        this.host = host;
        this.port = port;
        this.privateKey = privateKey;
    }

    public SFTPUtil() {
    }

    /**
     * 初始化ftp参数@param resultFileURL
     */
    public SFTPUtil(String resultFileURL, String keys) throws Exception {
        Map<String, String> map = parseSftp(resultFileURL);
        init(map.get("ipAddress"), map.get("ipPort"), map.get("userName"), map.get("passWord"), keys);
        log.info("ip: " + map.get("ipAddress"));
        log.info("port: " + map.get("ipPort"));
        log.info("userName: " + map.get("userName"));
        log.info("PassWord: " + map.get("passWord"));
    }

    /**
     * 初始化参数
     **/
    private void init(String ip, String portN, String userName, String passWord, String keys)
            throws Exception {
        if (StringUtils.isNotEmpty(portN)) {
            port = Integer.parseInt(portN);
        } else {
            port = 21;
        }
        if (StringUtils.isNotEmpty(keys)) {
            privateKey = keys;
        }
        host = new String(ip);
        sftp = new ChannelSftp();
        username = new String(userName);
        password = new String(passWord);
    }


    /**
     * 连接sftp服务器
     */
    public void login() throws JSchException {
//        try {
            JSch jsch = new JSch();
            if (privateKey != null) {
                jsch.addIdentity(privateKey);// 设置私钥
            }
            session = jsch.getSession(username, host, port);
            if (password != null) {
                session.setPassword(password);
            }
            Properties config = new Properties();
            config.put("StrictHostKeyChecking", "no");
            session.setConfig(config);
            session.connect();
            Channel channel = session.openChannel("sftp");
            channel.connect();
            sftp = (ChannelSftp) channel;
//            sftp.cd("/sas");
            log.info("登陆 Sftp Server Success");

//        } catch (JSchException e) {
//            e.printStackTrace();
//            log.error(e.getMessage());
//        }
    }

    /**
     * 关闭连接 server
     */
    public void logout() {
        if (sftp != null) {
            if (sftp.isConnected()) {
                sftp.disconnect();
            }
        }
        if (session != null) {
            if (session.isConnected()) {
                session.disconnect();
            }
        }
    }

    /**
     * 将输入流的数据上传到sftp作为文件。文件完整路径=basePath+directory
     *
     * @param basePath     服务器的基础路径
     * @param directory    上传到该目录
     * @param sftpFileName sftp端文件名
     */
    public void upload(String basePath, String directory, String sftpFileName, InputStream input) throws SftpException {
        try {
            sftp.cd(basePath);
            sftp.cd(directory);
        } catch (SftpException e) {
            //目录不存在，则创建文件夹
            String[] dirs = directory.split("/");
            String tempPath = basePath;
            for (String dir : dirs) {
                if (null == dir || "".equals(dir)) continue;
                tempPath += "/" + dir;
                try {
                    sftp.cd(tempPath);
                } catch (SftpException ex) {
                    sftp.mkdir(tempPath);
                    sftp.cd(tempPath);
                }
            }
        }
        sftp.put(input, sftpFileName);  //上传文件
    }


    /**
     * 下载文件。
     *
     * @param directory    下载目录
     * @param downloadFile 下载的文件
     * @param saveFile     存在本地的路径
     */
    public void download(String directory, String downloadFile, String saveFile) throws SftpException, FileNotFoundException {
        if (directory != null && !"".equals(directory)) {
            sftp.cd(directory);
        }
        File file = new File(saveFile);
        sftp.get(downloadFile, new FileOutputStream(file));
    }

    /**
     * 下载文件
     *
     * @param directory    下载目录
     * @param downloadFile 下载的文件名
     * @return 字节数组
     */
    public byte[] download(String directory, String downloadFile) throws SftpException, IOException {
        if (directory != null && !"".equals(directory)) {
            sftp.cd(directory);
        }
        InputStream is = sftp.get(downloadFile);

        byte[] fileData = IOUtils.toByteArray(is);

        return fileData;
    }


    /**
     * 删除文件
     *
     * @param directory  要删除文件所在目录
     * @param deleteFile 要删除的文件
     */
    public void delete(String directory, String deleteFile) throws SftpException {
        sftp.cd(directory);
        sftp.rm(deleteFile);
    }


    /**
     * 列出目录下的文件
     *
     * @param directory 要列出的目录
     */
    public List<String> listFiles(String directory) throws SftpException {
        List<String> fileNameList = new ArrayList<>();
        Vector ls = sftp.ls(directory);
        if (ls != null && ls.size() != 0){
            Iterator iterator = ls.iterator();
            while (iterator.hasNext()){
                Object next = iterator.next();
                String filename = ((ChannelSftp.LsEntry) next).getFilename();
                if (!".".equals(filename) && !"..".equals(filename) && filename.contains("."))
                    fileNameList.add(filename);
            }
        }
        return fileNameList;
    }


    /**
     * 列出目录下的文件
     * @param directory 文件所在目录
     * @param fromFileName 原文件名
     * @param toFileName 修改的文件名
     */
    public boolean renameFile(String directory,String fromFileName, String toFileName) {
        try {
            sftp.cd(directory);
            sftp.rename(fromFileName, toFileName);
            return true;
        } catch (Exception e) {
            return false;
        }
    }


    //上传文件测试
    public static void main(String[] args) throws SftpException, IOException, JSchException {
//        SFTPUtil sftp = new SFTPUtil("getech", "getech@1234", "10.88.40.83", 2294);
        SFTPUtil sftp = new SFTPUtil("baz", "xyz", "10.74.20.159", 31177);
        sftp.login();



//        List<String> list = sftp.listFiles("/upload");
//        System.out.println("11111");
        //上传
//        File file = new File("E:\\file\\image\\user\\avatar\\zhaikui_94f96929-7514-4b75-946c-8c1f3a50eb36.jpeg");
//        InputStream is = new FileInputStream(file);
//
//        sftp.upload("/upload", "/file/image", "kuige.jpeg", is);

        //下载
//        byte[] download = sftp.download("/upload/file/image", "kuige.jpeg");



        sftp.logout();
    }

    /***
     获取ftp内容
     @param
     @return
     */
    /*public String getFtpContent(String resultFileURL) {
        String str = null;
        log.info("SFTP getFtpContent Start");
        try {
            Map<String, String> map = parseSftp(resultFileURL);
            String ipAdress = map.get("ipAddress");
            int ipPort = SafeUtils.getInt(map.get("ipPort"), 21);
            String userName = map.get("userName");
            String passWord = map.get("passWord");
            log.info("sftp ipAdress=" + ipAdress + ",ipPort=" + ipPort + ",userName=" + userName + ",passWord=" + passWord);
            login();
            String path = map.get("path");
            path = path.replace("//", "/"); //防止双杠导致目录失败
            log.info("ftp path=" + path);

              *//*String changePath = path.substring(0, path.lastIndexOf("/")+1);
 log.info("ftp changePath="+changePath);*//*
            InputStream inputStream = sftp.get(path);
            BufferedReader br = new BufferedReader(new InputStreamReader(inputStream, "utf-8"));
            String data = null;
            StringBuffer resultBuffer = new StringBuffer();
            while ((data = br.readLine()) != null) {
                resultBuffer.append(data + "\n");
            }
            str = resultBuffer.toString();
            log.info("ftp content:" + str);
            logout();
        } catch (Exception e) {
            // TODO Auto-generated catch block254
            e.printStackTrace();
            log.error("ftp error:", e);
        }
        return str;
    }*/


    public static Map<String, String> parseSftp(String url) throws Exception {
        Map<String, String> temp = new HashMap<String, String>();
        String ipPort = "21";
        //由于 URL类解析 sftp地址会报错, 所以截取掉前面的s
        url = url.substring(1);
        URL urltemp = new URL(url);
        String ipAddress = urltemp.getHost();
        if (urltemp.getPort() != -1) {
            ipPort = urltemp.getPort() + "";
        }

        String path = urltemp.getPath();
        String userInfo = urltemp.getUserInfo();
        String userName = "";
        String userPwd = "";
        if (StringUtils.isNotEmpty(userInfo)) {
            String[] array = userInfo.split(":");
            if (array.length > 0) {
                userName = array[0];
            }

            if (array.length >= 1) {
                userPwd = array[1];
            }
        }
        temp.put("userName", userName);
        temp.put("passWord", userPwd);
        temp.put("ipAddress", ipAddress);
        temp.put("ipPort", ipPort);
        temp.put("path", path);

        return temp;
    }

}
